package com.linktrip.devicemanager.websocket.entity;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import com.linktrip.devicemanager.util.ByteUtil;
import com.linktrip.devicemanager.util.CRC8Util;

public class DataStruct {

	private int length;// 数据字节长度 2bytes
	private int protoVersion;// 协议版本号 2bytes
	private byte type; // 数据包类型 1byte 0x01:请求 , 0x02:响应 , 0x03:获取
	private short messageId;// 消息包编号,依次增加 2bytes
	private byte sosFlag;// 1byte 0x00=成功，0x01=解密失败，0x10=指令执行失败
	private String deviceId;// 车锁ID 8bytes
	private int lockStatus;// lock/unlock状态 1byte lock=1,unlock=2
	private int batteryStat;// 电池电量 1byte
	private byte blinkStatus;// 闪灯状态 1byte 1=闪灯，2=灭，3=常亮
	private int beepCount;// 蜂鸣次数 1byte 1-255
	private int sysVersion;// 当前固件版本号，结合Type下发时代表新版本号 1byte
	private int charge;// 1byte 高4位：充电输出和输入使能 0001-允许,0010-不允许 低4位：充电状态
						// 0001-充电中,0010-未充电
	private int mode;// 1byte 高4位：普通模式或异常模式 0000-普通模式,1000-异常模式 低4位：根据高4位，表示具体模式
						// 普通模式（0001=正常，0010=维护），异常模式（0001=异常移动）
	private int signature;// 1byte 签名，直接使用messageId低字节
	private double latitude;// 8byte 纬度
	private double longitude;// 8byte 经度
	private long timeStamp;// 8byte 时间戳
	private int hdwareVer;// 1byte
	private int temp;// 温度 1byte
	private int vBus;// 输入电源电压 1byte
	private int iCharge;// 充电电流 1byte
	private int vBattery;// 电池电压1byte
	private int na1;// 预留字段 1byte
	private int na2;// 预留字段 1byte
	private int crc;// 数据包CRC校验
	private short segmentCount;
	private short segmentId;
	private int crc32;
	private byte[] data; // 升级数据

	public int getLength() {
		if (0 == length)
			return 54;
		return length;
	}

	public void setLength(int length) {
		this.length = length;
	}

	public int getProtoVersion() {
		return protoVersion;
	}

	public void setProtoVersion(int protoVersion) {
		this.protoVersion = protoVersion;
	}

	public byte getType() {
		return type;
	}

	public void setType(byte type) {
		this.type = type;
	}

	public short getMessageId() {
		return messageId;
	}

	public void setMessageId(short messageId) {
		this.messageId = messageId;
	}

	public byte getSosFlag() {
		return sosFlag;
	}

	public void setSosFlag(byte sosFlag) {
		this.sosFlag = sosFlag;
	}

	public String getDeviceId() {
		return deviceId;
	}

	public void setDeviceId(String deviceId) {
		this.deviceId = deviceId;
	}

	public int getLockStatus() {
		return lockStatus;
	}

	public void setLockStatus(int lockStatus) {
		this.lockStatus = lockStatus;
	}

	public int getBatteryStat() {
		return batteryStat;
	}

	public void setBatteryStat(int batteryStat) {
		this.batteryStat = batteryStat;
	}

	public byte getBlinkStatus() {
		return blinkStatus;
	}

	public void setBlinkStatus(byte blinkStatus) {
		this.blinkStatus = blinkStatus;
	}

	public int getBeepCount() {
		return beepCount;
	}

	public void setBeepCount(int beepCount) {
		this.beepCount = beepCount;
	}

	public int getSysVersion() {
		return sysVersion;
	}

	public void setSysVersion(int sysVersion) {
		this.sysVersion = sysVersion;
	}

	public int getCharge() {
		return charge;
	}

	public void setCharge(int charge) {
		this.charge = charge;
	}

	public int getMode() {
		return mode;
	}

	public void setMode(int mode) {
		this.mode = mode;
	}

	public int getSignature() {
		return signature;
	}

	public void setSignature(int signature) {
		this.signature = signature;
	}

	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	public double getLongitude() {
		return longitude;
	}

	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}

	public long getTimeStamp() {
		return timeStamp;
	}

	public void setTimeStamp(long timeStamp) {
		this.timeStamp = timeStamp;
	}

	public int getHdwareVer() {
		return hdwareVer;
	}

	public void setHdwareVer(int hdwareVer) {
		this.hdwareVer = hdwareVer;
	}

	public int getTemp() {
		return temp;
	}

	public void setTemp(int temp) {
		this.temp = temp;
	}

	public int getvBus() {
		return vBus;
	}

	public void setvBus(int vBus) {
		this.vBus = vBus;
	}

	public int getiCharge() {
		return iCharge;
	}

	public void setiCharge(int iCharge) {
		this.iCharge = iCharge;
	}

	public int getvBattery() {
		return vBattery;
	}

	public void setvBattery(int vBattery) {
		this.vBattery = vBattery;
	}

	public int getNa1() {
		return na1;
	}

	public void setNa1(int na1) {
		this.na1 = na1;
	}

	public int getNa2() {
		return na2;
	}

	public void setNa2(int na2) {
		this.na2 = na2;
	}

	public int getCrc() {
		return crc;
	}

	public void setCrc(int crc) {
		this.crc = crc;
	}

	public short getSegmentCount() {
		return segmentCount;
	}

	public void setSegmentCount(short segmentCount) {
		this.segmentCount = segmentCount;
	}

	public short getSegmentId() {
		return segmentId;
	}

	public void setSegmentId(short segmentId) {
		this.segmentId = segmentId;
	}

	public int getCrc32() {
		return crc32;
	}

	public void setCrc32(int crc32) {
		this.crc32 = crc32;
	}

	public byte[] getData() {
		return data;
	}

	public void setData(byte[] data) {
		this.data = data;
	}

	public byte[] toByteArray() {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(bos);
		try {
			dos.writeShort(ByteUtil.convertShort((short) getLength())); // length

			dos.writeShort(ByteUtil.convertShort((short)0x02));// protoVersion

			dos.writeByte(getType());// Type

			dos.writeShort(ByteUtil.convertShort((short) getMessageId()));// MessageId
			dos.writeByte(0x00);// SOS_Flag

			dos.writeBytes("\0\0\0\0\0\0\0\0");// DeviceId

			dos.writeByte(getSysVersion());// SysVersion

			dos.writeByte(getMode());// Mode

			dos.writeByte(getLockStatus());// LockStatus

			dos.writeByte(0x00);// BatteryStat

			dos.writeByte(0x00);// Charge

			dos.writeByte(getBlinkStatus());// BlinkStatus

			dos.writeByte(getBeepCount());// BeepCount

			dos.writeByte(0x00);// Signature
			dos.writeBytes("\0\0\0\0\0\0\0\0");// Latitude

			dos.writeBytes("\0\0\0\0\0\0\0\0");// Longitude

			dos.write(ByteUtil.timeStamp2Bytes(timeStamp, getLockStatus() != 0 ?true:false));// TimeStamp

			dos.writeByte(getHdwareVer());// HdwareVer

			dos.writeByte(0x00);// Temp

			dos.writeByte(0x00);// vBus

			dos.writeByte(0x00);// iCharge

			dos.writeByte(0x00);// vBattery

			dos.writeByte(0x00);// NA

			dos.writeByte(0x00);// NA
			
			byte[] datas = new byte[53];
			System.arraycopy(bos.toByteArray(), 2, datas, 0, datas.length);
			byte cr = CRC8Util.crc8(datas, datas.length);
			setCrc(cr);
			dos.writeByte(getCrc());// CRC_8
			
			if (getLength() > 56) {
				dos.writeShort(ByteUtil.convertShort((short) getSegmentCount()));
				dos.writeShort(ByteUtil.convertShort((short) getSegmentId()));
				dos.writeBytes("\0\0\0\0");
			}

			return bos.toByteArray();
		} catch (IOException e) {
			e.printStackTrace();
			try {
				if (null != dos)
					dos.close();
				if (null != bos)
					bos.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		} finally {
			try {
				if (null != dos)
					dos.close();
				if (null != bos)
					bos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return null;
	}

	public byte[] toByteArray(byte[] body) {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(bos);
		try {
			dos.writeShort(ByteUtil.convertShort((short) getLength())); // length

			dos.writeShort(0x02);// protoVersion

			dos.writeByte(getType());// Type

			dos.writeShort(ByteUtil.convertShort((short) getMessageId()));// MessageId
			dos.writeByte(0x00);// SOS_Flag

			dos.writeBytes("\0\0\0\0\0\0\0\0");// DeviceId

			dos.writeByte(getSysVersion());// SysVersion

			dos.writeByte(getMode());// Mode

			dos.writeByte(getLockStatus());// LockStatus

			dos.writeByte(0x00);// BatteryStat

			dos.writeByte(0x00);// Charge

			dos.writeByte(getBlinkStatus());// BlinkStatus

			dos.writeByte(getBeepCount());// BeepCount

			dos.writeByte(0x00);// Signature
			dos.writeBytes("\0\0\0\0\0\0\0\0");// Latitude

			dos.writeBytes("\0\0\0\0\0\0\0\0");// Longitude

			dos.write(ByteUtil.timeStamp2Bytes(timeStamp, false));// TimeStamp

			dos.writeByte(getHdwareVer());// HdwareVer

			dos.writeByte(0x00);// Temp

			dos.writeByte(0x00);// vBus

			dos.writeByte(0x00);// iCharge

			dos.writeByte(0x00);// vBattery

			dos.writeByte(0x00);// NA

			dos.writeByte(0x00);// NA
			byte[] datas = new byte[53];
			System.arraycopy(bos.toByteArray(), 2, datas, 0, datas.length);
			byte cr = CRC8Util.crc8(datas, datas.length);
			setCrc(cr);
			dos.writeByte(getCrc());// CRC_8
			dos.writeShort(ByteUtil.convertShort((short) getSegmentCount()));
			dos.writeShort(ByteUtil.convertShort((short) getSegmentId()));
			if (body.length > 0) {
				dos.write(CRC8Util.crc32(body));
				dos.write(body);
			}

			return bos.toByteArray();
		} catch (IOException e) {
			e.printStackTrace();
			try {
				if (null != dos)
					dos.close();
				if (null != bos)
					bos.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		} finally {
			try {
				if (null != dos)
					dos.close();
				if (null != bos)
					bos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return null;
	}

	public static String checkLen(String tmp) {
		if (tmp.length() < 2)
			tmp = "0x0" + tmp;
		else
			tmp = "0x" + tmp;

		return tmp.toUpperCase();
	}

}
